package com.yyx.qq;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.yyx.qq.events.BaseQQListener;
import com.yyx.qq.jobs.BackgroundJobExecutor;
import com.yyx.qq.jobs.DownloadGroupJob;
import com.yyx.qq.jobs.DownloadSignatureJob;
import com.yyx.qq.jobs.GetFriendLevelJob;
import com.yyx.qq.jobs.GetFriendListJob;
import com.yyx.qq.jobs.IExecutor;
import com.yyx.qq.models.Cluster;
import com.yyx.qq.models.ClusterType;
import com.yyx.qq.models.ModelRegistry;
import com.yyx.qq.models.ModelUtils;
import com.yyx.qq.models.User;

import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.beans.ContactInfo;
import edu.tsinghua.lumaqq.qq.beans.Member;
import edu.tsinghua.lumaqq.qq.beans.QQFriend;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.events.QQEvent;
import edu.tsinghua.lumaqq.qq.packets.in.ClusterCommandReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;

class QQEventProcessor extends BaseQQListener {
	private QQMain main;
	// 登录重试次数，我这里处理最多重试6次
	// 如果第一次登录失败，则随机选择服务器重试3次
	// 如果依然失败，再随机选择服务器，并且强制使用tcp方式，再重试3次
	// 如果依然不行，报登录超时错误
	private int retryCount;

	/**
	 * 构造函数
	 */
	public QQEventProcessor(QQMain main) {
		this.main = main;
		retryCount = 0;
	}

	@Override
	protected void OnQQEvent(QQEvent e) {
		// TODO Auto-generated method stub
		switch (e.type) {
		case QQEvent.LOGIN_GET_TOKEN_FAIL:
			processLoginTimeout();
			break;
		case QQEvent.LOGIN_OK:
			processLoginSuccess();
			break;
		case QQEvent.LOGIN_FAIL:
			processLoginFail(e);
			break;
		case QQEvent.LOGIN_UNKNOWN_ERROR:
			processLoginUnknownError();
			break;
		case QQEvent.IM_SEND_OK:
			processSendIMSuccess();
			break;
		case QQEvent.IM_RECEIVED:
			processReceiveNormalIM(e);
			break;
		case QQEvent.USER_STATUS_CHANGE_OK:
			processChangeStatusSuccess();
			break;
		case QQEvent.USER_STATUS_CHANGE_FAIL:
			processChangeStatusFail();
			break;
		case QQEvent.SYS_TIMEOUT:
			switch (e.operation) {
			case QQ.QQ_CMD_SEND_IM:
				processSendIMFail();
			}
			break;
		case QQEvent.CLUSTER_GET_INFO_OK:
			processClusterGetInfoSuccess(e);
			break;
		case QQEvent.CLUSTER_GET_MEMBER_INFO_OK:
			processClusterGetMemberInfoSuccess(e);
			break;
		}
	}

	/**
	 * 处理登陆超时事件
	 * 
	 * @param e
	 *            QQEvent
	 */
	private void processLoginTimeout() {
		// 登录超时后自动重连
		retryCount++;
		if (retryCount > 6) {
			main.getClient().getUser().setStatus(QQ.QQ_STATUS_OFFLINE);
			main.logout();
			main.getUiHelper().setMessage(
					main.getText(R.string.message_box_login_fail).toString());
		} else {
			// 奇数次：随机使用服务器
			// 偶数次：随机使用服务器，强制使用TCP登录
			boolean forceTcp = retryCount % 2 == 0;
			QQUser me = main.getClient().getUser();
			byte status = me.getStatus();
			me.setStatus(QQ.QQ_STATUS_OFFLINE);
			main.logout();
			me.setStatus(status);
			main.checkLogin(true, forceTcp);
		}
	}

	/**
	 * 初始改变状态失败事件
	 */
	private void processChangeStatusFail() {
		main.getUiHelper().setMessage(
				main.getText(R.string.message_box_status_change_fail)
						.toString());
		main.logout();
	}

	/**
	 * 处理改变状态成功事件
	 */
	private void processChangeStatusSuccess() {
		main.getUiHelper().setMessage(
				main.getText(R.string.message_box_status_change_ok).toString());
	}

	/**
	 * 处理发送消息失败事件
	 */
	private void processSendIMFail() {
		main.getUiHelper().setMessage(
				main.getText(R.string.message_box_sys_timeout).toString());
		main.logout();
	}

	/**
	 * 处理发送消息成功事件
	 */
	private void processSendIMSuccess() {
		main.getUiHelper().setMessage(
				main.getText(R.string.message_box_send_ok).toString());
		main.logout();
	}

	/**
	 * 处理收到消息事件
	 * 
	 * @param e
	 * 		QQEvent
	 */
	private void processReceiveNormalIM(QQEvent e) {
		// 得到包，推入消息队列
		ReceiveIMPacket packet = (ReceiveIMPacket)e.getSource();
	    main.getMessageHelper().putNormalIM(packet);
	}
	
	/**
	 * 处理登陆成功事件
	 */
	private void processLoginSuccess() {
		
		main.getUiHelper().setMessage(
				main.getText(R.string.message_box_login_success).toString());
		if (main.getClient().getUser().isLoggedIn()) {
			//main.getMq().setPostpone(true);	//登陆成功，设置消息延迟处理    
			//TODO 读取配置文件，设置是否自动下载用户组，自动下载用户注释
			retryCount = 0;
			IExecutor executor = new BackgroundJobExecutor(main);
			//main.getMq().setPostpone(false);
			executor.addJob(new GetFriendListJob());
			executor.addJob(new DownloadGroupJob());
			
			//获取用户属性JOB
			executor.addJob(new DownloadSignatureJob());
			//得到好友级别的任务
			executor.addJob(new GetFriendLevelJob());
			
			//TODO 得到自定义图像任务
			
			// 启动任务
			if (executor.getAllJobCount() > 0)
				executor.execute();
		}
	}

	/**
	 * 处理登陆密码错误事件
	 * 
	 * @param e
	 */
	private void processLoginFail(QQEvent e) {
		main.getUiHelper().setMessage(
				main.getText(R.string.message_box_login_fail).toString());
		main.logout();
	}

	/**
	 * 处理登陆未知错误事件
	 */
	private void processLoginUnknownError() {
		processLoginTimeout();
	}

	/**
	 * 处理得到成员信息成功事件
	 * 
	 * @param e
	 *            QQEvent
	 */
	private void processClusterGetMemberInfoSuccess(QQEvent e) {
		ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e
				.getSource();
		Cluster c = ModelRegistry.getCluster(packet.clusterId);
		if (c != null) {
			// 对每个得到信息的成员，设置他们model的属性
			for (QQFriend friend : packet.memberInfos) {
				ContactInfo info = ModelUtils.createContact(friend);
				User f = ModelRegistry.getUser(friend.qqNum);
				if (f != null) {
					f.nick = friend.nick;
					f.headId = friend.head;
					f.member = friend.isMember();
					f.userFlag = friend.userFlag;
					f.female = !friend.isGG();
					f.info = info;
					if (!f.hasCardName())
						f.displayName = f.nick;
				}
				f = c.getMember(friend.qqNum);
				if (f != null) {
					f.nick = friend.nick;
					f.headId = friend.head;
					f.member = friend.isMember();
					f.info = info;
					f.userFlag = friend.userFlag;
					f.female = !friend.isGG();
					if (!f.hasCardName())
						f.displayName = f.nick;
				}
			}
		}
		// 刷新群组
		main.getUiHelper().refreshGroup();
	}

	/**
	 * <pre>
	 * 处理得到群信息成功事件，处理完毕后会相继请求群成员信息和在线成员列表，这个方法
	 * 在新增加一个群时会被调用。此外，如果群聊窗口打开后，20分钟请求一次群信息
	 * </pre>
	 * 
	 * @param e
	 *            QQEvent
	 */
	private void processClusterGetInfoSuccess(QQEvent e) {
		ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e
				.getSource();
		// 搜索这个群
		Cluster c = ModelRegistry.getCluster(packet.clusterId);
		// 群存在操作才有意义
		if (c != null) {
			if (packet.externalId == 0) {
				main.getUiHelper().removeCluster(packet.clusterId);
				return;
			}

			c.creator = packet.info.creator;
			c.authType = packet.info.authType;
			c.category = packet.info.category;
			c.oldCategory = packet.info.oldCategory;
			c.description = packet.info.description;
			c.notice = packet.info.notice;
			c.versionId = packet.info.versionId;
			c.externalId = packet.externalId;
			c.clusterType = ClusterType.NORMAL;
			c.name = packet.info.name;
			// 同步成员列表
			synchronizeMember(c, packet.members, false, 0);
			// 刷新群组
			main.getUiHelper().refreshGroup();
			// 请求得到成员信息
			main.getClient().cluster_GetMemberInfo(packet.clusterId,
					packet.members);
		}
	}

	/**
	 * 同步成员列表
	 */
	private void synchronizeMember(Cluster c, List<Member> newMembers,
			boolean tempCluster, int parentClusterId) {
		// 去掉重复的成员
		c.clearAdmins();
		c.clearStockholders();
		List<User> existMembers = new ArrayList<User>();
		List<Member> newMembersBak = new ArrayList<Member>(newMembers);
		for (Iterator<Member> i = newMembersBak.iterator(); i.hasNext();) {
			Member member = i.next();
			User u = c.removeMember(member.qq);
			if (u != null) {
				u.organizationId = member.organization;
				existMembers.add(u);
				i.remove();
				if (member.isAdmin())
					c.addAdmin(member.qq);
				else if (member.isStockholder())
					c.addStockholder(member.qq);
			}
		}

		// Map中剩下的成员为需要删除掉的成员
		c.removeAllMembers();
		// 恢复重复的成员
		for (User member : existMembers)
			c.addMember(member);
		// 添加新成员
		Cluster parent = null;
		if (tempCluster && parentClusterId != 0) {
			parent = ModelRegistry.getCluster(parentClusterId);
			if (c.group == null)
				parent.addSubCluster(c);
		}
		for (Member member : newMembersBak) {
			// 找到这个成员的model，如果是固定群，先从好友里面找
			// 如果是讨论组，从父群里面找，如果是多人对话，从好友里面找
			int qq = member.qq;
			User f = null;
			if (qq == main.getClient().getUser().getQQ())
				f = ModelRegistry.getUser(qq);
			else if (tempCluster) {
				if (parentClusterId == 0)
					f = ModelRegistry.getUser(qq);
				else if (parent != null)
					f = parent.getMember(qq);
			} else
				f = ModelRegistry.getUser(qq);

			// 没找到就新建一个
			if (f == null) {
				f = new User();
				f.qq = qq;
				f.nick = String.valueOf(qq);
				f.organizationId = member.organization;
			} else {
				try {
					f = (User) f.clone();
					f.organizationId = member.organization;
				} catch (CloneNotSupportedException e) {
					continue;
				}
			}
			c.addMember(f);
			if (member.isAdmin())
				c.addAdmin(member.qq);
			else if (member.isStockholder())
				c.addStockholder(member.qq);
		}
	}
}
